#include "QueryResult.h"
#include "../base/AsyncLog.h"


QueryResult::QueryResult(MYSQL_RES* result,uint64_t rowCount,uint32_t fieldCount)
 : m_fieldCount(fieldCount),m_rowCount(rowCount)
{   
    m_result = result;
    m_currentRow = new Field[m_fieldCount];

    MYSQL_FIELD* fields = mysql_fetch_fields(m_result);

    for(uint32_t i=0;i<m_fieldCount;i++ )
    {
        if(fields[i].name != nullptr)
        {
            m_fieldNames[i] = fields[i].name;
            m_vecFieldNames.push_back(fields[i].name);   
        }
        else
        {
            m_fieldNames[i] = "";
            m_vecFieldNames.push_back("");
        }
        
        m_currentRow[i].setType(convertNativeType(fields[i].type));
        
    }
}

QueryResult::~QueryResult()
{
    endQuery();
}

bool QueryResult::nextRow()
{
    MYSQL_ROW row;

    if(!m_result)
    {
        return false;
    }

    row = mysql_fetch_row(m_result);
    if(!row)
    {
        endQuery();
        return false;
    }

    unsigned long int * ulFieldLength;
    ulFieldLength = mysql_fetch_lengths(m_result);  //获得结果集的数据长度
    for(uint32_t i=0;i<m_fieldCount;i++)
    {
        if(row[i] == nullptr)
        {
            m_currentRow[i].setValid(false);
            m_currentRow[i].setValue("",0);
        }
        else
        {
            m_currentRow[i].setValid(true);
            m_currentRow[i].setValue(row[i],ulFieldLength[i]);
        }
        
        m_currentRow[i].setName(m_fieldNames[i]);
    }
    
    return true;
}

void QueryResult::endQuery()
{
    if(m_currentRow)
    {
        delete[] m_currentRow;
        m_currentRow = nullptr;
    }

    if(m_result)
    {
        mysql_free_result(m_result);
        m_result = nullptr;
    }
}

Field::DataTypes QueryResult::convertNativeType(enum_field_types mysqlType) const
{
    switch (mysqlType)
    {
        case FIELD_TYPE_TIMESTAMP:
        case FIELD_TYPE_DATE:
        case FIELD_TYPE_TIME:
        case FIELD_TYPE_DATETIME:
        case FIELD_TYPE_YEAR:
        case FIELD_TYPE_STRING:
        case FIELD_TYPE_VAR_STRING:
        case FIELD_TYPE_BLOB:
        case FIELD_TYPE_SET:
        case FIELD_TYPE_NULL:
            return Field::DB_TYPE_STRING;

        case FIELD_TYPE_TINY:
        case FIELD_TYPE_SHORT:
        case FIELD_TYPE_INT24:
        case FIELD_TYPE_LONGLONG:
        case FIELD_TYPE_ENUM:
            return Field::DB_TYPE_INTEGER;

        case FIELD_TYPE_DECIMAL:
        case FIELD_TYPE_FLOAT:
        case FIELD_TYPE_DOUBLE:
            return Field::DB_TYPE_FLOAT;
        default:
            return Field::DB_TYPE_UNKNOWN;
    }
}
